package com.aboverock.common.encrytor;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;

/**
 * The Class JasyptStringEncryptor.
 *
 * @author Rock Wang
 */
@Component
public class JasyptStringEncryptor implements StringEncryptor {

    private static final Logger log = LoggerFactory.getLogger(JasyptStringEncryptor.class);

    private static final String SALT = "RW52QEtCLVNtYXJ0";

    private PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();

    public JasyptStringEncryptor(Environment e) {
        createDefault(e);
    }

    private StringEncryptor createDefault(Environment e) {
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(getProperty(e, "jasypt.encryptor.password",
                new String(Base64Utils.decodeFromString(JasyptStringEncryptor.SALT))));
        config.setAlgorithm(getProperty(e, "jasypt.encryptor.algorithm", "PBEWithMD5AndDES"));
        config.setKeyObtentionIterations(getProperty(e, "jasypt.encryptor.keyObtentionIterations", "1000"));
        config.setPoolSize(getProperty(e, "jasypt.encryptor.poolSize", "1"));
        config.setProviderName(getProperty(e, "jasypt.encryptor.providerName", null));
        config.setProviderClassName(getProperty(e, "jasypt.encryptor.providerClassName", null));
        config.setSaltGeneratorClassName(getProperty(e, "jasypt.encryptor.saltGeneratorClassname",
                "org.jasypt.salt.RandomSaltGenerator"));
        config.setStringOutputType(getProperty(e, "jasypt.encryptor.stringOutputType", "base64"));
        encryptor.setConfig(config);
        return encryptor;
    }

    private static String getProperty(Environment environment, String key, String defaultValue) {
        if (!propertyExists(environment, key)) {
            log.info("Encryptor config not found for property {}, using default value: {}", key, defaultValue);
        }
        return environment.getProperty(key, defaultValue);
    }

    private static boolean propertyExists(Environment environment, String key) {
        return environment.getProperty(key) != null;
    }

    @Override
    public String encrypt(String message) {
        return encryptor.encrypt(message);
    }

    @Override
    public String decrypt(String encryptedMessage) {
        return encryptor.decrypt(encryptedMessage);
    }

}
